/*
Copyright 2011 Mary Suárez Machado

Este programa es de software libre: usted puede redistribuirlo y/o modificarlo según los términos de la Licencia de Gran pública de GNU como publicado por la Fundación de Software Libre, versión 3 de la Licencia, (o en su opción) cualquier versión posterior.

 Este programa es distribuido en la esperanza que será útil, pero SIN CUALQUIER GARANTÍA; sin aún la garantía implícita de VALOR COMERCIAL O SALUD PARA UN OBJETIVO PARTICULAR. Mirar la Licencia de Gran pública de GNU para más detalles.
*/


 /**
 *@file TablaDistancia.cpp
 *@brief Implementaciones de las funciones del módulo TablaDistancia
 *@author Mary Carmen Suarez
 *
 */

#include <iostream>
#include <cassert>
#include <TablaDistancia.h>

using namespace std;

TablaDistancia :: TablaDistancia ()
{
	int tam = 30;

//Creación de memoria dinámica
	codigo = new int[tam];
	nbits = new int[tam];
	distancia = new int *[tam];

	for(int i=0; i<tam; i++)
		distancia[i] = new int[2];

//Declaración de variables para la creación de la tabla
	int cod = 0; //el inicio de código de la tabla es de 0
	int bit = 0; //control de los nbits que tiene cada longitud
	int dist = 1; //el inicio de la distancia de la tabla es de 1

//Rellenado de la tabla
	for (int i=0; i<tam; i++)
	{
		if (i < 4)
		{
			codigo[i] = cod;
			nbits[i] = bit;
			distancia[i][0] = dist;
			distancia[i][1] = dist;
		}
		else
		{
			//Si a partir del 4 es par el número de bits aumenta en 1
			if (i%2 == 0)	bit++;
			codigo[i] = cod;
			nbits[i] = bit;
			distancia[i][0] = dist;
			//d=2^bit
			int d=1;
			for (int j=0; j<bit; j++)
				d *= 2;
			//la distancia del intervalo se haya como dist=dist+2^bit-1
			dist += d-1;
			distancia[i][1] = dist;
		}
		//incremento de código y distancia
		cod++;
		dist++;
	}
}

TablaDistancia :: ~TablaDistancia ()
{
	delete [] codigo;
	delete [] nbits;
	for (int i=0; i<30; i++)
		delete [] distancia[i];
	delete [] distancia;
}

void TablaDistancia :: Escribir () const
{
	for (int i=0; i<30; i++)
	{
		cout << codigo[i] << "----"<<nbits[i]<<"------";
		cout<<distancia[i][0]<<","<<distancia[i][1]<<endl;
	}
}

int TablaDistancia :: GetCodigo (int l) const
{
	assert (l >= 1 && l <= 32768);
	for (int i=0; i<30; i++)
		if (l >= distancia[i][0] && l <= distancia[i][1])
			return codigo[i];
    return 0; //no llega
}

int TablaDistancia :: GetBits (int l) const
{
	assert (l >= 1 && l <= 32768);
	for (int i=0; i<30; i++)
		if (l >= distancia[i][0] && l <= distancia[i][1])
			return nbits[i];
	return 0; //no llega
}

int TablaDistancia :: GetRangoLongitud (int l) const
{
	assert (l >= 1 && l <= 32768);
	for (int i=0; i<30; i++)
		if (l >= distancia[i][0] && l <= distancia[i][1])
			return distancia[i][0];
	return 0; //no llega
}
VectorBits TablaDistancia :: GetBitsAdicionales (int l) const
{
	assert (l >= 1 && l <= 32768);
	int bit = GetBits(l);
	int rango = GetRangoLongitud(l);
	int num = l - rango;
	VectorBits v(num,bit);
	return v;
}

int TablaDistancia :: PrimerRango (int cod)
{
	assert (cod >=0 && cod < 30);
	return distancia[cod][0];
}

int TablaDistancia :: NBits (int cod)
{
	assert (cod >=0 && cod < 30);
	return nbits[cod];
}
